﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SWGeneracionE.Models;
using SWGeneracionE.Libraries;

namespace SWGeneracionE.Controllers
{
    public class EventoController : BaseController
    {

        [Authorize]
        public ActionResult Eventos()
        {
            return View();
        }

        [Authorize]
        public ActionResult Habitaciones()
        {
            return View();
        }

        #region "Acciones Evento"
        [HttpPost]
        public JsonResult EventoList(int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
        {
            try
            {
                var eventosCount = 0;
                int idEventoActual = int.Parse(ViewBag.Evento);
                if (string.IsNullOrEmpty(jtSorting))
                    jtSorting = "nombre ASC";
                var eventos = UoW.eventoRepository.GetAllPaging(ref eventosCount, jtStartIndex, jtPageSize, jtSorting)
                    .Select(l => new
                    {
                        idEvento = l.idEvento,
                        nombre = l.nombre,
                        fechaInicio = l.fechaInicio,
                        fechaFin = l.fechaFin,
                        costoUSD = l.costoUSD,
                        costoLOC = l.costoLOC,
                        cupo = l.cupo,
                        costoBus = l.costoBus,
                        cupoHabitacion = l.cupoHabitacion,
                        observaciones = l.observaciones,
                        idLugar = l.idLugar,
                        actual = idEventoActual == l.idEvento
                    });

                return Json(new { Result = "OK", Records = eventos, TotalRecordCount = eventosCount });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error EventoList: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al obtener el listado de eventos." });
            }
        }

        [HttpPost]
        public JsonResult CreateEvento(Evento evento)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    AgregarBitacora("Error CreateEvento: Formulario inválido");
                    return Json(new
                    {
                        Result = "ERROR",
                        Message = "¡El formulario no es válido! " +
                        "Corrija e intente nuevemente."
                    });
                }

                UoW.eventoRepository.Add(evento);
                UoW.Save();
                var addedEvento = new 
                {
                    idEvento = evento.idEvento,
                    nombre = evento.nombre,
                    fechaInicio = evento.fechaInicio,
                    fechaFin = evento.fechaFin,
                    costoUSD = evento.costoUSD,
                    costoLOC = evento.costoLOC,
                    cupo = evento.cupo,
                    costoBus = evento.costoBus,
                    cupoHabitacion = evento.cupoHabitacion,
                    observaciones = evento.observaciones,
                    idLugar = evento.idLugar,
                    actual = false

                };
                AgregarBitacora("Creación de evento (CreateEvento): " + addedEvento.idEvento.ToString());
                return Json(new { Result = "OK", Record = addedEvento });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error CreateEvento: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = ex.Message });
            }
        }

        [HttpPost]
        public JsonResult UpdateEvento(Evento evento)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    AgregarBitacora("Error UpdateEvento: Formulario inválido");
                    return Json(new
                    {
                        Result = "ERROR",
                        Message = "¡El formulario no es válido! " +
                        "Corrija e intente nuevemente."
                    });
                }

                UoW.eventoRepository.Edit(evento);
                UoW.Save();
                AgregarBitacora("Actualización de evento (UpdateEvento): " + evento.idEvento.ToString());
                return Json(new { Result = "OK" });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error UpdateEvento: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al actualizar el evento." });
            }
        }

        [HttpPost]
        public JsonResult DeleteEvento(int idEvento)
        {
            try
            {
                Evento evento = UoW.eventoRepository.FindFirst(p => p.idEvento == idEvento);
                UoW.eventoRepository.Delete(evento);
                UoW.Save();
                AgregarBitacora("Eliminación de evento (DeleteEvento): " + idEvento.ToString());
                return Json(new { Result = "OK" });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error DeleteEvento: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al eliminar el evento." });
            }
        }

        [HttpPost]
        public JsonResult MarcarEvento(int idEvento)
        {
            try
            {
                int idAnterior = int.Parse(ViewBag.Evento);
                Parametro parametro = UoW.parametroRepository.FindFirst(p => p.idParametro == c_parametro_eventodefault);
                parametro.Valor = idEvento.ToString();
                UoW.parametroRepository.Edit(parametro);
                UoW.Save();
                AgregarBitacora("Actualizar evento actual (MarcarEvento): " + idEvento.ToString());
                return Json(new { Result = "OK", idAnterior = idAnterior , Message = "Se ha actualizado el evento actual" });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error MarcarEvento: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al actualizar evento actual." });
            }
        }
        #endregion

        #region "Acciones Habitacion"
        [HttpPost]
        public JsonResult HabitacionList(string apellidos, string nombres, string idGrupo, string descripcion, 
                                         string cantidadDePersonas, string noHabitacion, string edificio, 
                                         int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
        {
            try
            {
                if (!string.IsNullOrEmpty(apellidos))
                    apellidos = apellidos.Trim();
                else
                    apellidos = string.Empty;
                if (!string.IsNullOrEmpty(nombres))
                    nombres = nombres.Trim();
                else
                    nombres = string.Empty;
                if (string.IsNullOrEmpty(jtSorting))
                    jtSorting = "idGrupo ASC";
                var query = HabitacionListByFilter(apellidos, nombres, idGrupo, descripcion, cantidadDePersonas, noHabitacion, edificio)
                    .Select(l => new
                    {
                        idGrupo = l.idGrupo,
                        principal = l.AsignacionGrupo.FirstOrDefault(a => a.ParticipanteXEvento.Participante.nombres.Contains(nombres) 
                                && a.ParticipanteXEvento.Participante.apellidos.Contains(apellidos)),
                        descripcion = l.Descripcion,
                        cantidadDePersonas = l.CantidadDePersonas,
                        noHabitacion = l.NoHabitacion,
                        edificio = l.Edificio,
                        observaciones = l.Observaciones
                    });
                var queryF = query.Select(l => new
                    {
                        idGrupo = l.idGrupo,
                        principal = l.principal != null ? l.principal.ParticipanteXEvento.Participante.apellidos + ", " 
                                    + l.principal.ParticipanteXEvento.Participante.nombres : "",
                        descripcion = l.descripcion,
                        cantidadDePersonas = l.cantidadDePersonas,
                        noHabitacion = l.noHabitacion,
                        edificio = l.edificio,
                        observaciones = l.observaciones
                    });
                var queryG = queryF.OrderAndPaging(jtStartIndex, jtPageSize, jtSorting);

                //Ordenar por el valor indicado y Paginear
                var grupos = queryG.ToList();
                var gruposCount = query.Count();

                return Json(new { Result = "OK", Records = grupos, TotalRecordCount = gruposCount });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error HabitacionList: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al obtener el listado de habitaciones." });
            }
        }

        private IQueryable<Grupo> HabitacionListByFilter(string apellidos, string nombres, string idGrupo, string descripcion, 
                                                         string cantidadDePersonas, string noHabitacion, string edificio)
        {
            var query = from h in UoW.grupoRepository.GetAll()
                        select h;

            //validar datos
            if (!string.IsNullOrEmpty(apellidos))
                query = query.Where(h => h.AsignacionGrupo.FirstOrDefault(a => a.ParticipanteXEvento.Participante.apellidos.Contains(apellidos)) != null);
            if (!string.IsNullOrEmpty(nombres))
                query = query.Where(h => h.AsignacionGrupo.FirstOrDefault(a => a.ParticipanteXEvento.Participante.nombres.Contains(nombres)) != null);
            if (!string.IsNullOrEmpty(idGrupo))
            {
                int iGrupo = int.Parse(idGrupo);
                query = query.Where(h => h.idGrupo == iGrupo);
            }
            if (!string.IsNullOrEmpty(descripcion))
                query = query.Where(h => h.Descripcion.Contains(descripcion.Trim()));
            if (!string.IsNullOrEmpty(cantidadDePersonas))
            {
                int iCPersonas = int.Parse(cantidadDePersonas);
                query = query.Where(h => h.CantidadDePersonas == iCPersonas);
            }
            if (!string.IsNullOrEmpty(noHabitacion))
            {
                int iNoHabitacion = int.Parse(noHabitacion);
                query = query.Where(h => h.NoHabitacion == iNoHabitacion);
            }
            if (!string.IsNullOrEmpty(edificio))
                query = query.Where(h => h.Edificio == edificio);

            return query;
        }

        [HttpPost]
        public JsonResult CreateHabitacion(Grupo grupo)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    AgregarBitacora("Error CreateHabitacion: Formulario inválido");
                    return Json(new
                    {
                        Result = "ERROR",
                        Message = "¡El formulario no es válido! " +
                        "Corrija e intente nuevemente."
                    });
                }

                UoW.grupoRepository.Add(grupo);
                UoW.Save();
                var addedHabitacion = new
                {
                    idGrupo = grupo.idGrupo,
                    descripcion = grupo.Descripcion,
                    cantidadDePersonas = grupo.CantidadDePersonas,
                    noHabitacion = grupo.NoHabitacion,
                    edificio = grupo.Edificio,
                    observaciones = grupo.Observaciones
                };
                AgregarBitacora("Creación de habitación (CreateHabitacion): " + addedHabitacion.idGrupo.ToString());
                return Json(new { Result = "OK", Record = addedHabitacion });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error CreateHabitacion: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = ex.Message });
            }
        }

        [HttpPost]
        public JsonResult UpdateHabitacion(Grupo grupo)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    AgregarBitacora("Error UpdateHabitacion: Formulario inválido");
                    return Json(new
                    {
                        Result = "ERROR",
                        Message = "¡El formulario no es válido! " +
                        "Corrija e intente nuevemente."
                    });
                }

                UoW.grupoRepository.Edit(grupo);
                UoW.Save();
                AgregarBitacora("Actualización de grupo (UpdateHabitacion): " + grupo.idGrupo.ToString());
                return Json(new { Result = "OK" });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error UpdateHabitacion: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al actualizar la habitación." });
            }
        }

        [HttpPost]
        public JsonResult DeleteHabitacion(int idGrupo)
        {
            try
            {
                Grupo grupo = UoW.grupoRepository.FindFirst(p => p.idGrupo == idGrupo);
                UoW.grupoRepository.Delete(grupo);
                UoW.Save();
                AgregarBitacora("Eliminación de habitación (DeleteHabitacion): " + idGrupo.ToString());
                return Json(new { Result = "OK" });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error DeleteHabitacion: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al eliminar la habitación." });
            }
        }

        [HttpPost]
        public JsonResult AsignacionList(string idGrupo)
        {
            try
            {
                int iGrupo = int.Parse(idGrupo);
                var query = UoW.asignacionGrupoRepository.FindBy(a => a.idGrupo == iGrupo)
                    .Select(l => new
                    {
                        idAsignacionGrupo = l.idAsignacionGrupo,
                        idGrupo = l.idGrupo,
                        idParticipanteXEvento = l.idParticipanteXEvento,
                        codigo = l.ParticipanteXEvento.codigo,
                        nombre = l.ParticipanteXEvento.Participante.nombres + " " + l.ParticipanteXEvento.Participante.apellidos,
                        observaciones = l.observaciones
                    });

                //Ordenar por el valor indicado y Paginear
                var grupos = query.ToList();
                var gruposCount = query.Count();

                return Json(new { Result = "OK", Records = grupos, TotalRecordCount = gruposCount });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error AsignacionList: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al obtener el listado de asignaciones." });
            }
        }

        [HttpPost]
        public JsonResult AsignarHabitacion(string idGrupo, string codigo)
        {
            try
            {
                int idParticipanteXEvento = 0;
                int iGrupo = int.Parse(idGrupo);
                string nombre = "";
                //validar que codigo exista y este inscrito
                if (codigo != null)
                {
                    ParticipanteXEvento participante = UoW.participanteXEventoRepository
                        .FindFirst(t => t.codigo == codigo.Trim() && t.estado == Constantes.ESTADOPARTICIPANTE_INSCRITO);
                    if (participante != null)
                    {
                        idParticipanteXEvento = participante.idParticipanteXEvento;
                        nombre = participante.Participante.nombres + " " + participante.Participante.apellidos;
                    }
                    else
                    {
                        return Json(new
                        {
                            Result = "ERROR",
                            Message = "¡El código que ha ingresado no corresponde a ningún participante inscrito! <br/>" +
                                      "Corrija e intente nuevemente."
                        });
                    }
                }
                //validar no haya sido asignado
                AsignacionGrupo ag = UoW.asignacionGrupoRepository
                    .FindFirst(a => a.idParticipanteXEvento == idParticipanteXEvento);
                if (ag != null)
                {
                    return Json(new
                    {
                        Result = "ERROR",
                        Message = "¡El participante ya fue asignado a otra habitación (ID = " + ag.Grupo.idGrupo + ")! <br/>" +
                                  "Verifique."
                    });
                }
                //validar limite capacidad
                int idEventoActual = int.Parse(ViewBag.Evento);
                Evento eventoActual = UoW.eventoRepository.FindFirst(e => e.idEvento == idEventoActual);
                int iCapacidad = (int)eventoActual.cupoHabitacion;
                int asignacionCount = UoW.asignacionGrupoRepository.FindBy(e => e.idGrupo == iGrupo)
                    .Count();
                if (asignacionCount >= iCapacidad)
                {
                    return Json(new
                    {
                        Result = "ERROR",
                        Message = "¡La habitación ya ha llegado a su capacidad máxima! <br/>" +
                                  "Verifique."
                    });
                }
                //todo bien, realice asignación
                AsignacionGrupo asignacion = new AsignacionGrupo
                {
                    idGrupo = iGrupo,
                    idParticipanteXEvento = idParticipanteXEvento
                };
                UoW.asignacionGrupoRepository.Add(asignacion);
                UoW.Save();
                var addedAsignacion = new
                {
                    idAsignacionGrupo = asignacion.idAsignacionGrupo,
                    idGrupo = asignacion.idGrupo,
                    idParticipanteXEvento = asignacion.idParticipanteXEvento,
                    codigo = codigo,
                    nombre = nombre,
                    observaciones = asignacion.observaciones
                };
                AgregarBitacora("Asignación de habitación (AsignarHabitacion): " + addedAsignacion.idGrupo.ToString());
                return Json(new { Result = "OK", Record = addedAsignacion });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error AsignarHabitacion: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = ex.Message });
            }
        }

        [HttpPost]
        public JsonResult UpdateAsignacion(AsignacionGrupo asignacion)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    AgregarBitacora("Error UpdateAsignacion: Formulario inválido");
                    return Json(new
                    {
                        Result = "ERROR",
                        Message = "¡El formulario no es válido! " +
                        "Corrija e intente nuevemente."
                    });
                }

                UoW.asignacionGrupoRepository.Edit(asignacion);
                UoW.Save();
                AgregarBitacora("Actualización de asignación (UpdateAsignacion): " + asignacion.idGrupo.ToString());
                return Json(new { Result = "OK" });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error UpdateAsignacion: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al actualizar la asignación." });
            }
        }

        [HttpPost]
        public JsonResult DeleteAsignacion(int idAsignacionGrupo)
        {
            try
            {
                AsignacionGrupo asignacion = UoW.asignacionGrupoRepository.FindFirst(p => p.idAsignacionGrupo == idAsignacionGrupo);
                UoW.asignacionGrupoRepository.Delete(asignacion);
                UoW.Save();
                AgregarBitacora("Eliminación de asignación (DeleteAsignacion): " + asignacion.ToString());
                return Json(new { Result = "OK" });
            }
            catch (Exception ex)
            {
                AgregarBitacora("Error DeleteAsignacion: " + ex.Message + "--" + ex.Source);
                return Json(new { Result = "ERROR", Message = "Ocurrio un error al eliminar la asignación." });
            }
        }

        public ExcelResult AsignacionExportExcel(string apellidos, string nombres, string idGrupo, string descripcion, string cantidadDePersonas,
                                                 string noHabitacion, string edificio)
        {
            try
            {
                //validar los 5 filtros
                var consulta = HabitacionListByFilter(apellidos, nombres, idGrupo, descripcion, cantidadDePersonas, noHabitacion, edificio)
                    .ToList();

                var contador = consulta.Count;
                //se crea el objeto con los encabezados y datos que iran en la hoja de excel
                var excelData = new ExcelData();
                excelData.headers = new string[10];
                excelData.contents = new string[contador, 10];
                excelData.headers[0] = "ID";
                excelData.headers[1] = "Descripción";
                excelData.headers[2] = "Capacidad";
                excelData.headers[3] = "Edificio";
                excelData.headers[4] = "No. Habitación";
                excelData.headers[5] = "Huesped 1";
                excelData.headers[6] = "Huesped 2";
                excelData.headers[7] = "Huesped 3";
                excelData.headers[8] = "Huesped 4";
                excelData.headers[9] = "Observaciones";

                var i = 0;
                //se llenan los datos según los obtenidos en la consulta
                foreach (var habitacion in consulta)
                {
                    excelData.contents[i, 0] = habitacion.idGrupo.ToString();
                    excelData.contents[i, 1] = habitacion.Descripcion;
                    excelData.contents[i, 2] = habitacion.CantidadDePersonas.ToString();
                    excelData.contents[i, 3] = habitacion.Edificio;
                    excelData.contents[i, 4] = habitacion.NoHabitacion.ToString();
                    int j = 5;
                    foreach (var asignacion in habitacion.AsignacionGrupo)
                    {
                        if (j > 8) break;
                        excelData.contents[i, j] = asignacion.ParticipanteXEvento.codigo + "  -  " + asignacion.ParticipanteXEvento.Participante.nombres + " " + asignacion.ParticipanteXEvento.Participante.apellidos;
                        j++;
                    }
                    excelData.contents[i, 9] = habitacion.Observaciones;
                    
                    i++;
                }

                //Devolver vista parcial
                return new ExcelResult("AsignacionesGE.xls", PartialView("_ExcelTemplate", excelData));

            }
            catch (Exception ex)
            {
                AgregarBitacora("Error AsignacionExportExcel: " + ex.Message + "--" + ex.Source);
                return null;
            }
        }
        #endregion
    }
}
